#ifndef BIGNUM_H
#define BIGNUM_H
#include <iostream>
using std::ostream; 
using std::istream;
#include <vector>
using std::vector;
class BigNum {
#define BASE 10 //基数
#define DLEN 4 
    //一个整形对应的基数位: $\lfloor log_{BASE}\sqrt{INT\_MAX} \rfloor$
#define EBASE 10000 
    //扩展基数: $BASE^DLEN = BASE^{\lfloor log_{BASE}\sqrt{INT\_MAX} \rfloor}$
#define MAXBIT EBASE*EBASE
public:
    vector<int> d; //采用倒序整型数组表示
        //每个整数表示一个扩展的基数位，低位在前, 高位在后
private:
    static int value_cmp(vector<int> const &a, vector<int> const &b);
    BigNum op_div_mod(BigNum const &opt, bool get_mod) const;
public:
    BigNum(void) {} //default 0
    BigNum(int const); //int to bn
    BigNum(char const *); //string to bn
    BigNum(BigNum const &b) : d(b.d) {}
    friend istream& operator>>(istream&,BigNum&);
    friend ostream& operator<<(ostream&,BigNum const &);
    BigNum &operator= (BigNum const &opt) { d = opt.d; return *this; }
    BigNum &operator+= (BigNum const &opt);
    BigNum &operator-= (BigNum const &opt);
    BigNum &operator*= (const BigNum &opt);
    BigNum &operator/= (BigNum const &b);
    BigNum operator+ (const BigNum &) const;
    BigNum operator- (const BigNum &) const;
    BigNum operator* (const BigNum &) const;
    BigNum operator/ (BigNum const &opt) { return op_div_mod(opt, false); }
    BigNum operator% (BigNum const &opt) { return op_div_mod(opt, true); }

    bool operator== (const BigNum &) const;
    bool operator!= (BigNum const &b) const { return value_cmp(d, b.d)!=0; }
    bool operator> (const BigNum &) const;
    bool operator< (const BigNum &) const;
    bool operator>= (const BigNum &) const;
    bool operator<= (const BigNum &) const;

    BigNum operator++(void);
    BigNum operator--(void);
    BigNum operator^ (int const &) const;

    ~BigNum () {}
    void clear(void); //处理进位和借位

    //对于short int型操作数可以进行定制处理
    BigNum &operator+= (short const &ops);
    BigNum &operator-= (short const &ops);
    BigNum &operator*= (short const &ops);
    BigNum operator+ (short const &ops) const { 
        BigNum ret(*this); 
        ret += ops; 
        return ret; 
    } 
    BigNum operator- (short const &ops) const {
        BigNum ret(*this); 
        ret -= ops; 
        return ret; 
    }
    BigNum operator* (short const &ops) const {
        BigNum ret(*this); 
        ret *= ops; 
        return ret; 
    }
};
#endif //BIGNUM_H
